package com.ftwj.demo.utils.file;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ftwj.demo.utils.exception.FileException;
import com.ftwj.demo.utils.logs.LoggerUtil;

public class ZipCompressor {

	private static final int FIle_BUFFER_SIZE = 1024 * 10;

	private File zipFile;

	public ZipCompressor(String pathName) {
		zipFile = new File(pathName);
	}

	/**
	 *	 读取zip文件内容
	 * 
	 */
	public static void readZip( String zipPath, String charset) {
		ZipEntry zipEntry = null;
		File fileOut = null;// ZipInputStream读取压缩文件
		try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zipPath), Charset.forName(charset));
				BufferedInputStream bufferedInputStream = new BufferedInputStream(zipInputStream);
				FileOutputStream fileOutputStream = new FileOutputStream(fileOut);
				BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);) {
			while ((zipEntry = zipInputStream.getNextEntry()) != null) {
				String fileName = zipEntry.getName();
				if (zipEntry.isDirectory()) {
					// TODO
				} else {
					int b = 0;
					while ((b = bufferedInputStream.read()) != -1) {
						bufferedOutputStream.write(b);
					}
				}
			}
		} catch (IOException e) {
			throw new FileException("压缩文件读取失败", e);
		}
	}

	/**
	 * 	压缩成ZIP
	 * 
	 * @param srcFiles  需要压缩的文件列表
	 * @param --zipFile 压缩文件输出位置
	 * @throws RuntimeException 压缩失败会抛出运行时异常
	 */
	public static void filesToZip(List<File> srcFiles, String zipFile) {
		long start = System.currentTimeMillis();
		File file = new File(zipFile);
		File parentFile = file.getParentFile();
		if (!parentFile.exists()) {
			parentFile.mkdirs();
		}
		try (OutputStream outputstream = new FileOutputStream(file);
				ZipOutputStream zos = new ZipOutputStream(outputstream);) {
			for (File srcFile : srcFiles) {
				byte[] buf = new byte[FIle_BUFFER_SIZE];
				zos.putNextEntry(new ZipEntry(srcFile.getName()));
				int len;
				FileInputStream in = new FileInputStream(srcFile);
				while ((len = in.read(buf)) != -1) {
					zos.write(buf, 0, len);
				}
				zos.closeEntry();
				in.close();
			}
			long end = System.currentTimeMillis();
			LoggerUtil.info("压缩完成，耗时：{} ms", (end - start));
		} catch (Exception e) {
			throw new RuntimeException("文件压缩失败", e);
		}
	}

	public void compress(List<String> pathName) {
		try (FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
				CheckedOutputStream cos = new CheckedOutputStream(fileOutputStream, new CRC32());
				ZipOutputStream out = new ZipOutputStream(cos);) {
			String basedir = "";
			for (int i = 0; i < pathName.size(); i++) {
				compress(new File(pathName.get(i)), out, basedir);
			}
			out.close();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public void compress(String srcPathName) {
		File file = new File(srcPathName);
		if (!file.exists())
			throw new RuntimeException(srcPathName + "不存在！");
		try (FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
				CheckedOutputStream cos = new CheckedOutputStream(fileOutputStream, new CRC32());
				ZipOutputStream out = new ZipOutputStream(cos);) {
			String basedir = "";
			compress(file, out, basedir);
			out.close();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private void compress(File file, ZipOutputStream out, String basedir) {
		/* 判断是目录还是文件 */
		if (file.isDirectory()) {
			System.out.println("压缩：" + basedir + file.getName());
			this.compressDirectory(file, out, basedir);
		} else {
			System.out.println("压缩：" + basedir + file.getName());
			this.compressFile(file, out, basedir);
		}
	}

	/** 压缩一个目录 */
	private void compressDirectory(File dir, ZipOutputStream out, String basedir) {
		if (!dir.exists())
			return;

		File[] files = dir.listFiles();
		for (int i = 0; i < files.length; i++) {
			/* 递归 */
			compress(files[i], out, basedir + dir.getName() + "/");
		}
	}

	/** 压缩一个文件 */
	private void compressFile(File file, ZipOutputStream out, String basedir) {
		if (!file.exists()) {
			return;
		}
		try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));) {
			ZipEntry entry = new ZipEntry(basedir + file.getName());
			out.putNextEntry(entry);
			int count;
			byte data[] = new byte[FIle_BUFFER_SIZE];
			while ((count = bis.read(data, 0, FIle_BUFFER_SIZE)) != -1) {
				out.write(data, 0, count);
			}
			bis.close();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static void main(String[] args) {
		ZipCompressor zc = new ZipCompressor("C:\\Users\\Administrator\\Desktop\\download.zip");
		List<String> list = new ArrayList<>();
		list.add("C:\\Users\\Administrator\\Desktop\\飞天网景公司LOGO使用申请单.docx");
		list.add("C:\\Users\\Administrator\\Desktop\\系统权限审批表.doc");
		list.add("C:\\Users\\Administrator\\Desktop\\中医药资源信息.txt");
		zc.compress(list);
	}
}